<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Knowledge Graph Viewer</title>
    <link href="https://unpkg.com/vis-network@7.7.0/standalone/umd/vis-network.min.css" rel="stylesheet" type="text/css" />
    <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" integrity="sha512-iBBXm8fW90+nuLcSKlbmrPcLa0OT92xO1BIsZ+ywDWZCvqsWgccV3gFoRBv0z+8dLJgyAHIhR35VZc2oM/gI1w==" crossorigin="anonymous" referrerpolicy="no-referrer" />
    <script type="text/javascript" src="https://unpkg.com/vis-network@7.7.0/standalone/umd/vis-network.min.js"></script>
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>

    <style>
    html, body {
        height: 100%;
        margin: 0;
    }
    select, input, button {
        display: inline-block;
        margin-left: 10px;
        margin-top: 10px;
    }
    #graph {
        width: 100%;
        height: 100%;
        border: 1px solid lightgray;
    }
     .bubble {
        padding: 8px 12px;
        border-radius: 10px;
        margin-bottom: 10px;
        display: inline-block;
    }

    .user-message {
        background-color: #87CEFA;
        color: white;
        align-self: flex-end;
    }

    .response-message {
        background-color: #F0E68C;
    }

    #messages {
        display: flex;
        flex-direction: column;
    }

    #close-button {
        background-color: white;
        border: none;
        color: #666;
        font-weight: bold;
        cursor: pointer;
        padding: 0;
        font-size: 16px;
        line-height: 18px;
        width: 18px;
        height: 18px;
        text-align: center;
        border-radius: 50%;
    }

    #chat-window {
        resize: both;
        overflow-y: hidden;
    }

    .switch {
        position: relative;
        display: inline-block;
        width: 40px;
        height: 20px;
        margin-left: 5px;
    }

    .switch input {
        opacity: 0;
        width: 0;
        height: 0;
    }

    .slider {
        position: absolute;
        cursor: pointer;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background-color: #ccc;
        -webkit-transition: .4s;
        transition: .4s;
    }

    .slider:before {
        position: absolute;
        content: "";
        height: 16px;
        width: 16px;
        left: 2px;
        bottom: 2px;
        background-color: white;
        -webkit-transition: .4s;
        transition: .4s;
    }

    input:checked + .slider {
        background-color: #2196F3;
    }

    input:focus + .slider {
        box-shadow: 0 0 1px #2196F3;
    }

    input:checked + .slider:before {
        -webkit-transform: translateX(20px);
        -ms-transform: translateX(20px);
        transform: translateX(20px);
    }

    .slider.round {
        border-radius: 20px;
    }

    .slider.round:before {
        border-radius: 50%;
    }

     .slider {
            pointer-events: auto;
            cursor: pointer;
     }

     .tooltip {
        position: absolute;
        display: none;
        background: rgba(0, 0, 0, 0.8);
        color: #fff;
        padding: 5px;
        border-radius: 3px;
        font-size: 12px;
        white-space: nowrap;
    }

    #clear-button {
            background-color: white;
            border: 1px solid lightgray;
            color: #666;
            font-weight: bold;
            padding: 5px;
            cursor: pointer;
            font-size: 14px;
            line-height: 18px;
            width: 50px;
            height: 26px;
            text-align: center;
            border-radius: 5px;
            margin-right: 10px;
        }

        #header {
            display: flex;
            justify-content: space-between;
            align-items: center;
        }

        #left-content {
            display: flex;
            align-items: center;
        }

        #right-content {
            display: flex;
            align-items: center;
        }

        #clear-button-container {
            margin: 0 auto
        }

</style>
</head>
<body>
    <div style="height: 10%; padding-left: 10px;">
        <select id="kg_name_selector" style="width: 100px;">
        </select>
        <input id="entity_name_input" type="text" placeholder="Entity Name" style="width: 150px;">
        <button id="search_button">Search</button>
        <button id="display_button">Display</button>
    </div>
    <div id="graph" style="height: 90%;">
        <!-- 图谱将在此容器中显示 -->
    </div>

    <button id="dialog_button" style="position: fixed; right: 20px; bottom: 20px;">Dialog</button>

    <!-- 聊天窗口 -->
    <div id="chat-window" style="display:none; position:fixed; right:10px; bottom:10px; width:300px; height:400px; background-color:white; border:1px solid lightgray; border-radius:5px;">
        <div id="header" style="height: 30px; background-color: #f0f0f0; padding: 0 10px;">
            <div id="left-content">
                <label for="llm-toggle" style="border: none; padding-top: 5px;">LLM:</label>
                <div class="switch">
                    <input type="checkbox" id="llm-toggle" checked>
                    <span class="slider round"></span>
                </div>
                <span tabindex="0" class="ml-2" data-toggle="tooltip" data-placement="top" title="用户需要提供openai的访问关键字，才能启动LLM功能，具体请见README">
                    <i class="fas fa-info-circle"></i>
                </span>
            </div>
            <div id="clear-button-container" style="border: none; padding-bottom: 10px;">
                <button id="clear-button" class="btn btn-danger">Clear</button>
            </div>
            <div id="right-content">
                <button id="close-button" style="background-color: transparent; border: none;">&times;</button>
            </div>
        </div>
        <div id="messages" style="height: calc(80% - 30px); overflow-y: auto; padding: 10px;"></div>
        <div style="height: 20%; display: flex; align-items: center; padding: 0 10px;">
            <input id="message-input" type="text" placeholder="Enter your message" style="flex-grow: 1; margin-right: 10px;">
            <button id="send-button" style="width: 50px;">Send</button>
        </div>
    </div>



    <script>
        // 请求所有知识图谱名称并填充下拉菜单
        function load_kg_names() {
            $.get('http://localhost:5500/get_all_kg_names', function (data) {
                var kg_name_selector = $('#kg_name_selector');
                kg_name_selector.empty();
                data.forEach(function (kg_name) {
                    kg_name_selector.append($('<option>').text(kg_name));
                });
            });
        }

        function get_type_color_mappings(kg_name, callback) {
            $.get('http://localhost:5500/get_type_color_mappings', {kg_name: kg_name}, function (data) {
                var type_color_map = {};
                data.forEach(function (item) {
                    type_color_map[item.entity_type] = item.color;
                });
                callback(type_color_map);
            });
        }


        // 修改此函数以接受 type_color_map 参数
        function convert_data_to_vis_format(data, type_color_map) {
            var nodes = [];
            var edges = [];

            if (!data.entities || data.entities.length === 0) {
                nodes.push({
                    id: 'not_found',
                    label: '没有查找到相应实体',
                    shape: 'circle',
                    color: 'grey' // 设置一个显眼的颜色，如红色
                });
            } else {
                    data.entities.forEach(function (entity) {
                        nodes.push({
                            id: entity.vertex_id,
                            label: entity.vertex_name,
                            shape: 'circle',
                            color: type_color_map[entity.vertex_type] // 使用 color 变量设置颜色
                        });
                    });

                    if (data.relations && data.relations.length > 0) {
                        data.relations.forEach(function (relation) {
                            edges.push({
                                from: relation.source_vertex_id,
                                to: relation.target_vertex_id,
                                label: relation.edge_type
                            });
                        });
                    }
            }
            return {
                nodes: nodes,
                edges: edges
            };
        }

        // 在图谱容器中显示图谱
        function display_graph(data, type_color_map) { // 添加 type_color_map 参数
            var container = document.getElementById('graph');
            var graph_data = convert_data_to_vis_format(data, type_color_map); // 将 type_color_map 传递给此函数
            var options = {
                edges: {
                    font: {
                        size: 12, // 设置字体大小
                        align: 'middle' // 设置字体位置
                    },
                    arrows: {
                        to: {
                            enabled: true, // 显示箭头指向目标节点
                            scaleFactor: 0.5 // 设置箭头大小
                        }
                    }
                }
            };

            var network = new vis.Network(container, graph_data, options);
            console.log('Display finished');
        }

        // 显示和隐藏对话框
        function toggle_dialog() {
            const chatWindow = $('#chat-window');
            if (chatWindow.is(':visible')) {
                chatWindow.hide();
            } else {
                chatWindow.show();
            }
        }

        function request_dialog_api(kg_name, query, is_llm_enabled, callback) {
            // 将 is_llm_enabled 作为参数传递给 API
            $.get('http://localhost:5500/dialog', { kg_name: kg_name, query: query, is_llm_enabled: is_llm_enabled }, function (data) {
                //console.log("Received response:", data.resp_message);
                callback(data.resp_message);
            });
        }

        function add_message_to_chat_window(message, is_response) {
            var messages = $('#messages');
            var message_element = $('<p>').text(message).addClass('bubble');

            if (is_response) {
                message_element.addClass('response-message');
            } else {
                message_element.addClass('user-message');
            }

            messages.append(message_element);
            messages.scrollTop(messages.prop('scrollHeight')); // 滚动到底部
        }

        function check_openai_key() {
            $.get('http://localhost:5500/check_openai_key', function (data) {
                if (!data.key_exists) {
                    console.log("key file doesn't exist.");
                    $('#llm-toggle').prop('checked', false); // 新增：设置 LLM 开关为关闭状态
                    $('#llm-toggle').prop('disabled', true);
                    $('#tooltip').text('用户需要提供openai 的访问关键字，才能启动LLM功能，具体请见README');
                }
            });
        }

        // 设置按钮事件处理程序
        $(document).ready(function () {
            // 加载知识图谱名称
            load_kg_names();

            // 搜索按钮
            $('#search_button').click(function () {
                var kg_name = $('#kg_name_selector').val();
                var entity_name = $('#entity_name_input').val();
                if (kg_name && entity_name) {
                    // 调用 search API
                    $.get('http://localhost:5500/search', {kg_name: kg_name, entity_name: entity_name}, function (data) {
                        // 如果返回的数据中存在错误，显示错误信息
                        if (data.error) {
                            alert(data.error);
                            return;
                        }

                        // 获取 type_color_map 并调用 display_graph 函数
                        get_type_color_mappings(kg_name, function (type_color_map) {
                            display_graph(data, type_color_map);
                        });
                    });
                }
            });

            // 修改显示按钮事件处理程序以获取 type_color_map
            $('#display_button').click(function () {
                $('#entity_name_input').val('');

                var kg_name = $('#kg_name_selector').val();
                if (kg_name) {
                    $.get('http://localhost:5500/get_kg_data', {kg_name: kg_name}, function (data) {
                            get_type_color_mappings(kg_name, function (type_color_map) {
                            display_graph(data, type_color_map); // 将 type_color_map 传递给此函数
                        });
                    });
                }
            });

            check_openai_key();

            // LLM 开关提示
            //$('.slider').on('click', function() {
            //    const checkbox = $(this).prev();
            //    checkbox.prop('checked', !checkbox.prop('checked'));
            //});

            // LLM 开关提示
            $('.slider').on('click', function() {
                const checkbox = $(this).prev();
                if (!checkbox.prop('disabled')) { // 新增：当 LLM 开关不被禁用时才能够切换状态
                    checkbox.prop('checked', !checkbox.prop('checked'));
                }
            });

            // 对话按钮
            $('#dialog_button').click(function () {
                toggle_dialog();
            });

            $('#send-button').click(function () {
                var kg_name = $('#kg_name_selector').val();
                var message = $('#message-input').val();
                $('#message-input').val(''); // 清空输入框

                // 获取 LLM 开关的状态
                var is_llm_enabled = $('#llm-toggle').prop('checked');

                if (kg_name && message) {
                    add_message_to_chat_window(message, false); // 添加用户消息
                    request_dialog_api(kg_name, message, is_llm_enabled, function (resp_message) {
                        add_message_to_chat_window(resp_message, true); // 添加后端响应消息
                    });
                }
            });

            $('#message-input').on('keypress', function (e) {
                if (e.which == 13) {
                    e.preventDefault();
                    $('#send-button').click();
                }
            });

            // 关闭按钮
            $('#close-button').click(function () {
                toggle_dialog();
            });

            // 清除按钮
            $('#clear-button').click(function () {
                $('#messages').empty(); // Clear the ChatWindow content
            });

        });
    </script>
</body>
</html>

